home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / system / pmw114.zip / PMODEW.DOC < prev    next >
Text File  |  1995-01-28  |  73KB  |  2,046 lines

  1. ------------------------------------------------------------------------------
  2. ---------------------- PMODE For Watcom C/C++ - v1.14 ------------------------
  3. ------------------------------------------------------------------------------
  4.  
  5.   This is the documentation for PMODE for Watcom C/C++ - v1.14, henceforth
  6. referred to as PMODE/W. PMODE/W is Copyright (c) 1994, Charles Scheffold and
  7. Thomas Pytel. All rights reserved.
  8.  
  9. Contents:
  10. ---------
  11.  
  12. 1 - Overview
  13.     1.0  - Legal disclaimer
  14.     1.1  - Description
  15.     1.2  - Usage
  16.     1.3  - Performance and compatibility
  17.     1.4  - PMODE/W protected mode
  18.     1.5  - PMODE/W execution
  19.     1.6  - Terms for non-commercial use
  20.     1.7  - Licensing PMODE/W for commercial use
  21.     1.8  - Contact information
  22.  
  23. 2 - Supported DPMI INT 31h functions
  24.     2.0  - Function 0000h - Allocate Descriptors
  25.     2.1  - Function 0001h - Free Descriptor
  26.     2.2  - Function 0003h - Get Selector Increment Value
  27.     2.3  - Function 0006h - Get Segment Base Address
  28.     2.4  - Function 0007h - Set Segment Base Address
  29.     2.5  - Function 0008h - Set Segment Limit
  30.     2.6  - Function 0009h - Set Descriptor Access Rights
  31.     2.7  - Function 000Ah - Create Alias Descriptor
  32.     2.8  - Function 000Bh - Get Descriptor
  33.     2.9  - Function 000Ch - Set Descriptor
  34.     2.10 - Function 0100h - Allocate DOS Memory Block
  35.     2.11 - Function 0101h - Free DOS Memory Block
  36.     2.12 - Function 0102h - Resize DOS Memory Block
  37.     2.13 - Function 0200h - Get Real Mode Interrupt Vector
  38.     2.14 - Function 0201h - Set Real Mode Interrupt Vector
  39.     2.15 - Function 0204h - Get Protected Mode Interrupt Vector
  40.     2.16 - Function 0205h - Set Protected Mode Interrupt Vector
  41.     2.17 - Function 0300h - Simulate Real Mode Interrupt
  42.     2.18 - Function 0301h - Call Real Mode Procedure With Far Return Frame
  43.     2.19 - Function 0302h - Call Real Mode Procedure With IRET Frame
  44.     2.20 - Function 0303h - Allocate Real Mode Callback Address
  45.     2.21 - Function 0304h - Free Real Mode Callback Address
  46.     2.22 - Function 0305h - Get State Save/Restore Addresses
  47.     2.23 - Function 0306h - Get Raw Mode Switch Addresses
  48.     2.24 - Function 0400h - Get Version
  49.     2.25 - Function 0500h - Get Free Memory Information
  50.     2.26 - Function 0501h - Allocate Memory Block
  51.     2.27 - Function 0502h - Free Memory Block
  52.     2.28 - Function 0503h - Resize Memory Block
  53.     2.29 - Function 0800h - Physical Address Mapping
  54.     2.30 - Function 0801h - Free Physical Address Mapping
  55.     2.31 - Function 0900h - Get and Disable Virtual Interrupt State
  56.     2.32 - Function 0901h - Get and Enable Virtual Interrupt State
  57.     2.33 - Function 0902h - Get Virtual Interrupt State
  58.  
  59. 3 - Supported DOS extended INT 21h functions
  60.     3.0  - Function 09h - Write String to Standard Output
  61.     3.1  - Function 1Ah - Set Disk Transfer Area
  62.     3.2  - Function 1Bh - Get Allocation Information for Default Drive
  63.     3.3  - Function 1Ch - Get Allocation Information for Specific Drive
  64.     3.4  - Function 1Fh - Get Drive Parameter Block for Default Drive
  65.     3.5  - Function 25h - Set Interrupt Vector
  66.     3.6  - Function 2Fh - Get Disk Transfer Area
  67.     3.7  - Function 32h - Get Drive Parameter Block for Specific Drive
  68.     3.8  - Function 34h - Get Address of InDOS Flag
  69.     3.9  - Function 35h - Get Interrupt Vector
  70.     3.10 - Function 39h - Create Subdirectory
  71.     3.11 - Function 3Ah - Remove Subdirectory
  72.     3.12 - Function 3Bh - Set Directory
  73.     3.13 - Function 3Ch - Create File
  74.     3.14 - Function 3Dh - Open File
  75.     3.15 - Function 3Fh - Read From File
  76.     3.16 - Function 40h - Write to File
  77.     3.17 - Function 41h - Delete File
  78.     3.18 - Function 43h - Get/Set File Attributes
  79.     3.19 - Function 47h - Get Directory Path
  80.     3.20 - Function 48h - Allocate Memory Block
  81.     3.21 - Function 49h - Free Memory Block
  82.     3.22 - Function 4Ah - Resize Memory Block
  83.     3.23 - Function 4Bh - Sub-Function 00h - Load and Execute Program
  84.     3.24 - Function 4Eh - Search for First Filename Match
  85.     3.25 - Function 4Fh - Search for Next Filename Match
  86.     3.26 - Function 56h - Rename File
  87.  
  88. 4 - Supported mouse extended INT 33h functions
  89.     4.0  - Function 0009h - Define Graphics Cursor
  90.     4.1  - Function 000Ch - Define Interrupt Subroutine Parameters
  91.     4.2  - Function 0016h - Save Driver State
  92.     4.3  - Function 0017h - Restore Driver State
  93.  
  94. ------------------------------------------------------------------------------
  95. ------------------------------ 1 - Overview ----------------------------------
  96. ------------------------------------------------------------------------------
  97.  
  98.   This section will give you all the information you will need to plug PMODE/W
  99. right into your Watcom C/C++ protected mode programs. All of the other things
  100. you need to be aware of about using PMODE/W commercially and non-commercially
  101. are also in this section. Specific information on INT 31h and INT 21h DOS
  102. extended services supported by PMODE/W is in the following sections. Please
  103. note that we have only tested this extender with Watcom C/C++ versions 9.5 and
  104. 10.0.
  105.  
  106. 1.0 - Legal disclaimer:
  107. -----------------------
  108.  
  109.   We exclude any and all implied warranties, including warranties of
  110. merchantability and fitness for a particular purpose. We make no warranty or
  111. representation, either express or implied, with respect to PMODE/W, its
  112. quality, performance, merchantability, or fitness for a particular purpose.
  113. We shall have no liability for special, incidental, or consequential damages
  114. arising out of or resulting from the use, misuse, or modification of PMODE/W.
  115.  
  116.   All trademarks used in this documentation are property of their respective
  117. owners.
  118.  
  119. 1.1 - Description:
  120. ------------------
  121.  
  122.   PMODE/W is basically a direct replacement for DOS/4GW, the default extender
  123. for Watcom C/C++. PMODE/W itself is confined within a single small EXE file.
  124. This EXE file is what you make your stub at link time, basically replacing the
  125. DOS/4GW stub which searches the path for DOS/4GW and re-executes it on the
  126. original program. Programs linked with the PMODE/W extender do not need any
  127. big, bulky external program to execute. When a PMODE/W program is executed,
  128. the extender within the EXE does all the setup necessary and runs the
  129. protected mode portion of that EXE. A nice feature of PMODE/W programs is that
  130. you can always run them with DOS/4GW if you wish. Executing DOS/4GW on a
  131. PMODE/W program will cause the PMODE/W extender in the EXE to be ignored and
  132. DOS/4GW will basically just run the protected mode portion of the program
  133. itself. This also means you can debug PMODE/W programs just as easily by
  134. using the debugger that is part of the Watcom C/C++ package.
  135.  
  136.   All in all, PMODE/W gives you a great deal of flexibility. You may do all of
  137. your development with PMODE/W, but if you are unsatisfied with the performance
  138. or with any other aspect of PMODE/W, you may switch back to DOS/4GW at any
  139. time quite easily. This also applies the other way around: do all of your
  140. development with DOS/4GW, then for the release version use PMODE/W. There are
  141. other extenders available for Watcom C/C++ and they do provide a lot more
  142. 'stuff', but they do not approach PMODE/W in terms of speed and size.
  143.  
  144.   To be fair, we must note the disadvantages of PMODE/W. It does lack that
  145. 'stuff' which the other more professional extenders posess. The good point
  146. being it also lacks the overhead of supporting that 'stuff'. For example,
  147. PMODE/W does absolutely no exception trapping whatsoever. This is purely an
  148. ideological thing. We do not wish to slow down the IRQ process in ANY way at
  149. all. We know (since we do a lot of it) that there are applications where the
  150. lowest possible interrupt latency is required. Exception handlers would force
  151. us to slow down IRQ response (reprogramming the PICs is out of the question).
  152. However, this is not a major loss as you should not be getting exceptions in a
  153. release version of a program anyway. During development you can always run
  154. DOS/4GW on your code to provide exception trapping.
  155.  
  156.   To sum it up, if you are looking for a good solid, stable, and fast
  157. extender, you need look no further. If frills are what you want, PMODE/W may
  158. not be the best choice for you.
  159.  
  160. Here are the advantages of PMODE/W:
  161.  
  162. ) No external extender required (everything needed to execute is in the EXE).
  163. ) Small size (less than 9k for the entire extender program).
  164. ) Low memory overhead.
  165. ) Does not require ANY extended memory to load OR execute.
  166. ) No annoying initialization messages.
  167. ) Fast execution time.
  168. ) Free for non-commercial use.
  169.  
  170. 1.2 - Usage:
  171. ------------
  172.  
  173.   The following main files should be present in your PMODE/W archive (probably
  174. among various BBS ads and other junk):
  175.  
  176. ) PMODEW.EXE    - The actual PMODE/W DOS extender.
  177. ) PMODEW.DOC    - The documentation you are now reading.
  178. ) PMODEW.LNK    - Example linker initialization file for PMODE/W.
  179. ) MAKEEX.BAT    - Batch file that builds some example programs.
  180. ) PMWSETUP.EXE  - PMODE/W parameter setup program.
  181.  
  182.   There will also be present a few example C files. You may just run MAKEEX
  183. to build the example files and then run them for your own satisfaction. You
  184. will probably want to add a new system, PMODE/W, to your WLSYSTEM.LNK file.
  185. All you need to do in this case is add the contents of PMODEW.LNK to your
  186. WLSYSTEM.LNK file, this will add the system 'pmodew' to your Watcom C/C++
  187. setup. You may also just compile to a 'dos4g' system but replace the stub with
  188. PMODEW.EXE.
  189.  
  190.   The PMWSETUP program will set up the default parameters for protected mode
  191. under PMODE/W either within the PMODEW.EXE file itself, or in any program that
  192. has been compiled with PMODE/W. These parameters will be discussed in more
  193. detail later on in this document, for now let it suffice to say that they
  194. control PMODE/W behavior in such a way that they do not need to be modified
  195. very often, usually never. If you modify the parameters in PMODEW.EXE, they
  196. will take effect in any program compiled with PMODE/W from that point on.
  197.  
  198. 1.3 - Performance and compatibility:
  199. ------------------------------------
  200.  
  201.   Our major concerns in developing PMODE/W were speed, size, and stability.
  202. PMODE/W itself was written entirely in assembly (unlike some extenders we
  203. know). When running under PMODE/W your code will be running at a privilege
  204. level of zero, the highest and fastest. PMODE/W does not virtualize anything,
  205. and does not invoke any protected mode mechanism that is slow. For example,
  206. if the system is running clean or under XMS, PMODE/W does not turn on paging.
  207. Under a memory manager which provides both VCPI and DPMI services, PMODE/W
  208. will opt for VCPI protected mode which is significantly faster than DPMI. When
  209. PMODE/W makes calls to real mode, it switches the system into actual real mode
  210. rather than the slower V86 mode (when it can, under VCPI this is not possible,
  211. control must be passed back to the VCPI server). In terms of speed, when your
  212. code is running under PMODE/W, it is running as fast as the system will allow.
  213.  
  214.   In terms of size on disk, we need say no more than for you to look at the
  215. size of the PMODE/W executable and compare it to that other extender. In terms
  216. of memory size, you may do tests yourself to confirm that PMODE/W does indeed
  217. suck up a lot less memory at run-time than the competition. In fact, PMODE/W
  218. will run even if there is absolutely no extended memory in the system
  219. (assuming of course there is enough low memory for the program). To be fair,
  220. we must say we squished the PMODE/W executable with our own compression
  221. program written expressly for the purpose (this demonstrates the extent we
  222. took most of our optimizations to).
  223.  
  224.   As for compatibility, PMODE/W is fully compatible with DOS/4GW as far as
  225. Watcom C/C++ is concerned. PMODE/W extends only those DOS functions required
  226. by the Watcom C/C++ libraries (though this is a good deal of them). The
  227. exception is BIOS INT 13h functions, which PMODE/W does not extend. PMODE/W
  228. also provides a subset of DPMI 0.9 INT 31h functions in protected mode. We do
  229. not emulate DOS/4GW though, as none of its API functions are duplicated by
  230. PMODE/W. PMODE/W will run under a clean system, XMS, VCPI, or DPMI. Though
  231. you should be aware that under a DPMI system, PMODE/W will not be providing
  232. the DPMI functions, but rather the actual DPMI host in the system will. You
  233. should also be aware that PMODE/W will leave the A20 line enabled when calling
  234. real mode. Disabling the A20 for real mode is not really necessary, it is a
  235. big slowdown during mode switches to have to enable/disable the A20, so
  236. PMODE/W avoids it.
  237.  
  238. 1.4 - PMODE/W protected mode:
  239. -----------------------------
  240.  
  241.   For those of you who are familiar with it, the PMODE/W kernel is based on
  242. the PMODE 3 kernel by Thomas Pytel that has been available in the public
  243. domain for some time now. If you have a good working knowlege of PMODE 3, then
  244. you pretty much know the workings of the PMODE/W kernel. There are some
  245. differences though. The memory system has been completely changed, as has the
  246. behavior of the IRQs. You should read this section even if you know PMODE 3.
  247.  
  248.   When run under a clean system, XMS, or VCPI, PMODE/W has control of
  249. protected mode. In this case, it can set up the system to run as fast as
  250. possible under the various conditions. Under DPMI, the DPMI host of the system
  251. will have full protected mode control and PMODE/W will install its DOS
  252. extensions on top of that. If the system provides both VCPI and DPMI services,
  253. PMODE/W will use the VCPI services for faster execution (unless instructed not
  254. to by the setup program). When PMODE/W does have protected mode control (under
  255. clean/XMS/VCPI), it runs all code at a privilege level of zero. In addition,
  256. under a clean or XMS system, paging will not be enabled. This is only a minor
  257. speed increase, but there is no real need to manage paging.
  258.  
  259.   PMODE/W provides a subset of DPMI 0.9 function calls and general
  260. functionality when a DPMI host is not present. PMODE/W will pass any software
  261. interrupts from protected to their default real mode handlers (provided no
  262. protected mode handlers have been installed for them), just as DPMI will. The
  263. general registers will be passed on to the real mode handler, but the segment
  264. registers can not be as they have different meanings in real and protected
  265. mode. The flags will be passed back from the real mode handler. This provides
  266. a simple interface to all real mode interrupt routines which do not take
  267. parameters in the segment registers, for example, INT 16h function 00h.
  268.  
  269.   Any IRQs that occur in protected mode and have not been hooked by a
  270. protected mode handler will be sent on to their real mode handlers. If an IRQ
  271. occurs in real mode, and a protected mode handler has hooked that IRQ, it will
  272. be sent to the protected mode handler first. The protected mode handler may
  273. chain to the real mode handler for that IRQ by calling the previous protected
  274. mode handler for that IRQ. This behavior is in accordance with the DPMI
  275. standard. If you hook a protected mode IRQ (INT 31h function 0205h), then hook
  276. the same IRQ in real mode (INT 31h function 0201h), the protected mode handler
  277. will be called if the IRQ occurs in protected mode, and the real mode handler
  278. will handle the IRQs if they occur in real mode. Setting up two handlers like
  279. this assures minimal latency. This means a handler will get control when the
  280. IRQ occurs as soon as physically possible.
  281.  
  282.   You should be aware that PMODE/W does not pass INTs 1ch, 23h, or 24h to
  283. protected mode from real mode as is specified in DPMI documentation. This
  284. means that if you want to hook the BIOS timer tick routine or the DOS break or
  285. critical error interrupt, you must set up a real mode handler for them,
  286. possibly a real mode callback. Another departure by PMODE/W from official DPMI
  287. specifications is in extended memory allocation. DPMI documentation states
  288. that the block of extended memory allocated through function 0501h is
  289. guaranteed at least paragraph alignment. The PMODE/W DPMI implementation will
  290. enforce only DWORD alignment.
  291.  
  292.   This is only a brief description of the workings of the PMODE/W kernel. If
  293. you want more information on the internals, grab a copy of the PMODE v3 kernel
  294. available publicly on the internet and BBSes. Except for the memory system and
  295. IRQ hooking, PMODE v3 is very similar to the PMODE/W kernel (being that the
  296. PMODE/W kernel is based on it).
  297.  
  298. 1.5 - PMODE/W execution:
  299. ------------------------
  300.  
  301.   When a PMODE/W executable is run, PMODE/W will attempt to switch the system
  302. into protected mode and load the protected mode portion of the same
  303. executable. If there is some error, not enough memory, or a system
  304. incompatibility, PMODE/W will exit with an error message. If loading was
  305. successful, PMODE/W will pass execution control on to the program. PMODE/W
  306. will load any 16bit code and data into low memory, but 32bit code and data may
  307. be loaded into low or extended memory depending on avaliability.
  308.  
  309.   There are a number of modifiable parameters in the PMODE/W extender
  310. executable that affect protected mode execution. For the most part, these
  311. parameters deal with memory. PMODE/W allocates one large block of extended
  312. memory for its pool from which it provides memory to its client program. There
  313. is a maximum value for the extended memory to be allocated. By default, the
  314. maximum is all of the extended memory in the system. The maximum value
  315. reflects the size of the block you want PMODE/W to take from the system, not
  316. necessarily the size of the largest block available to the default C/C++
  317. malloc functions. You may set the maximum to zero to indicate you do not want
  318. PMODE/W to allocate ANY extended memory.
  319.  
  320.   Another variable specifies the amount of low memory for PMODE/W to TRY to
  321. keep free. If PMODE/W can, it will accommodate this value by loading 32bit
  322. code and data into extended memory. If there is not enough extended memory
  323. available for this, 32bit code and data will be loaded into low memory anyway.
  324. If PMODE/W can not keep this much low memory free, it will not exit with an
  325. error message. Setting this parameter to a high value will in effect duplicate
  326. the DOS/4GW behavior of loading all 32bit code and data into extended memory.
  327. If you do not necessarily need any extra low memory free during the execution
  328. of your program, you may set this value to zero.
  329.  
  330.   There is a group of parameters that specify the number and size of nested
  331. mode switch stacks. Whenever you do a call to real mode, or a callback or IRQ
  332. is passed from real mode to its hook in protected mode, a nested stack is
  333. used. These parameters have meaning only if the program is not run under a
  334. DPMI system. If a DPMI host is in place when the program is run, it provides
  335. its own nested stacks for mode switches. The number of nested stacks directly
  336. affects the number of nested mode switches your program can do using the
  337. various mode switch methods. The size of both the real mode and protected mode
  338. nested stacks can also be specified. By default, these values are high enough
  339. for normal operation. However, if you are intending to use a lot of stack
  340. variables in a protected mode IRQ handler, or a lot of recursive calls, you
  341. may need to increase the size of the protected mode nested stacks. The more
  342. nested stacks you specify and the larger they are, the more low memory is
  343. needed by PMODE/W during execution.
  344.  
  345.   Another group of variables that has meaning only under clean/XMS/VCPI
  346. execution specify the number of selectors and DPMI callbacks you want PMODE/W
  347. to make available. The more selectors and callbacks you want, the more low
  348. memory is used by PMODE/W, though the amount of low memory used for each is
  349. quite low so that large numbers of each can be specified. There will usually
  350. be a little less than the number of selectors you request available to your
  351. program due to the protected mode system and C/C++ code using some of them.
  352.  
  353.   There are three other misc parameters that can be set. There is a maximum
  354. number of page tables to use under a VCPI system. Each page table allocated
  355. requires 4k of low memory to be used by PMODE/W and maps 4M of memory. This
  356. directly affects the maximum amount of extended memory available under a VCPI
  357. system. This parameter is only the maximum number of page tables to allow. At
  358. run-time, only as many page tables will be allocated as are needed. Under a
  359. clean/XMS system, no page tables are required, so this parameter has no
  360. meaning. But under VCPI, you may want to restrict the number of page tables to
  361. save low memory if you do not need more than a certain amount of extended
  362. memory. This puts a maximum ceiling on extended memory under VCPI which may be
  363. lower than the maximum actually specified in the other variable. The second
  364. parameter specifies the order of DPMI and VCPI detection. By default, VCPI
  365. will be checked before DPMI, but you may set DPMI to be checked before VCPI.
  366. The third variable specifies how many pages to reserve for physical address
  367. mapping calls (INT 31h function 0800h) under VCPI. Each page will allow you to
  368. map up to 4M of address space and takes up 4k of extended memory. So for
  369. example, if you intend to map a 2M frame buffer of a video card, you will need
  370. only one page. You may set this parameter to zero if you do not intend to map
  371. any physical addresses.
  372.  
  373.   The setup program PMWSETUP will allow you to modify these variables in the
  374. PMODE/W extender itself, or specifically, in any program compiled with
  375. PMODE/W. The setup program will enforce any necessary minimums and maximums
  376. for the values, but there are certain things you should be aware of. You will
  377. be allowed to set the number of nested protected mode stacks to zero. But keep
  378. in mind this will only work if you do not use any DPMI callbacks and do not
  379. hook any IRQs in protected mode. Also, do not specify any less than two real
  380. mode nested stacks if you will be calling the old IRQ handler in a protected
  381. mode IRQ handler. It is wise to keep the number of nested stacks above 4, but
  382. if you follow these strict rules, you may set the number lower to save some
  383. low memory. If you set these numbers lower, and get problems, try increasing
  384. them and the associated stack sizes.
  385.  
  386.   In the setup program itself, the arrow keys move the selection bar, SPACE
  387. toggles hex/decimal display, and ENTER modifies the currently selected value.
  388.  
  389. 1.6 - Terms for non-commercial use:
  390. -----------------------------------
  391.  
  392.   You are hereby permitted to use this DOS extender in any and all
  393. non-commercial and non-shareware software programs free of any financial
  394. obligation to us, provided that if the program is distributed, it is
  395. distributed to the public, free of any charge for the program itself. There is
  396. no restriction on what kind of reselling of the above mentioned program is
  397. done (shareware houses, CD-ROMs, etc...), as long as the program is available
  398. to the public with no financial obligation to the author(s). The only thing we
  399. ask in this case is that you credit us in your production for the DOS
  400. extender. It would also be nice, but not necessary, if you dropped us a note
  401. informing us of your use of PMODE/W in some production.
  402.  
  403. 1.7 - Licensing PMODE/W for commercial use:
  404. -------------------------------------------
  405.  
  406.   If you wish to use PMODE/W in a commercial, shareware, or any program which
  407. is to be sold or has attached to it an obligation to buy something, you MUST
  408. purchase a commercial distribution license. This license will allow royalty
  409. free distribution of one application using PMODE/W. A separate license is
  410. required for each application in which PMODE/W is used. A single licensed
  411. application may consist of more than one actual program, but all the programs
  412. within that application must be available only as part of the whole package
  413. and may not be sold separately for their own intrinsic value.
  414.  
  415.   The license fee is $500 U.S. for a commercial or shareware program. Once
  416. purchased, this license is valid for the life of the program, including any
  417. and all major revisions.
  418.  
  419. 1.8 - Contact information:
  420. --------------------------
  421.  
  422.   If you are interested in licensing PMODE/W for a commercial or shareware
  423. program, you may contact us in the following manner:
  424.  
  425. ) Send mail to:
  426.  
  427.     Ryan Cramer
  428.     8300 Riding Ridge Place
  429.     McLean, VA  22102
  430.     USA
  431.  
  432. ) Send E-mail to:
  433.  
  434.     rcramer1@osf1.gmu.edu
  435.  
  436. ) Drop a note to the sysop on the Data Connection BBS at:
  437.  
  438.     +1-703-506-8598
  439.     +1-703-847-0861
  440.  
  441. ) For technical questions, drop a note to:
  442.  
  443.     daredevi@dorsai.dorsai.org
  444.  
  445. ------------------------------------------------------------------------------
  446. ------------------- 2 - Supported DPMI INT 31h functions ---------------------
  447. ------------------------------------------------------------------------------
  448.  
  449.   PMODE/W duplicates a subset of DPMI protected mode functions. These
  450. functions are available ONLY in protected through INT 31h. They provide
  451. descriptor services, extended memory services, interrupt services, translation
  452. services, and some other misc things. A function is called by setting AX to
  453. the function code, setting any other registers for the function, and executing
  454. an INT 31h. Upon return, the carry flag will be clear if the function was
  455. successful. If the carry flag is set, the function failed. All other registers
  456. are preserved unless otherwise specified. In addition to the functions listed
  457. here, functions 0600h and 0601h will return with the carry flag clear to stay
  458. compatible with code that locks memory since PMODE/W does not support virtual
  459. memory.
  460.  
  461. 2.0 - Function 0000h - Allocate Descriptors:
  462. --------------------------------------------
  463.  
  464.   Allocates one or more descriptors in the client's descriptor table. The
  465. descriptor(s) allocated must be initialized by the application with other
  466. function calls.
  467.  
  468. In:
  469.   AX     = 0000h
  470.   CX     = number of descriptors to allocate
  471.  
  472. Out:
  473.   if successful:
  474.     carry flag clear
  475.     AX       = base selector
  476.  
  477.   if failed:
  478.     carry flag set
  479.  
  480. Notes:
  481. ) If more that one descriptor was requested, the function returns a base
  482.   selector referencing the first of a contiguous array of descriptors. The
  483.   selector values for subsequent descriptors in the array can be calculated
  484.   by adding the value returned by INT 31h function 0003h.
  485.  
  486. ) The allocated descriptor(s) will be set to expand-up writeable data, with
  487.   the present bit set and a base and limit of zero. The privilege level of the
  488.   descriptor(s) will match the client's code segment privilege level.
  489.  
  490. 2.1 - Function 0001h - Free Descriptor:
  491. ---------------------------------------
  492.  
  493.   Frees a descriptor.
  494.  
  495. In:
  496.   AX     = 0001h
  497.   BX     = selector for the descriptor to free
  498.  
  499. Out:
  500.   if successful:
  501.     carry flag clear
  502.  
  503.   if failed:
  504.     carry flag set
  505.  
  506. Notes:
  507. ) Each descriptor allocated with INT 31h function 0000h must be freed
  508.   individually with the function. Even if it was previously allocated as part
  509.   of a contiguous array of descriptors.
  510.  
  511. ) Under DPMI 1.0/VCPI/XMS/raw, any segment registers which contain the
  512.   selector being freed are zeroed by this function.
  513.  
  514. 2.2 - Function 0003h - Get Selector Increment Value:
  515. ----------------------------------------------------
  516.  
  517.   The Allocate Descriptors function (0000h) can allocate an array of
  518. contiguous descriptors, but only return a selector for the first descriptor.
  519. The value returned by this function can be used to calculate the selectors for
  520. subsequent descriptors in the array.
  521.  
  522. In:
  523.   AX     = 0003h
  524.  
  525. Out:
  526.   always successful:
  527.     carry flag clear
  528.     AX       = selector increment value
  529.  
  530. Notes:
  531. ) The increment value is always a power of two.
  532.  
  533. 2.3 - Function 0006h - Get Segment Base Address:
  534. ------------------------------------------------
  535.  
  536.   Returns the 32bit linear base address from the descriptor table for the
  537. specified segment.
  538.  
  539. In:
  540.   AX     = 0006h
  541.   BX     = selector
  542.  
  543. Out:
  544.   if successful:
  545.     carry flag clear
  546.     CX:DX  = 32bit linear base address of segment
  547.  
  548.   if failed:
  549.     carry flag set
  550.  
  551. Notes:
  552. ) Client programs must use the LSL instruction to query the limit for a
  553.   descriptor.
  554.  
  555. 2.4 - Function 0007h - Set Segment Base Address:
  556. ------------------------------------------------
  557.  
  558.   Sets the 32bit linear base address field in the descriptor for the specified
  559. segment.
  560.  
  561. In:
  562.   AX     = 0007h
  563.   BX     = selector
  564.   CX:DX  = 32bit linear base address of segment
  565.  
  566. Out:
  567.   if successful:
  568.     carry flag clear
  569.  
  570.   if failed:
  571.     carry flag set
  572.  
  573. Notes:
  574. ) Under DPMI 1.0/VCPI/XMS/raw, any segment register which contains the
  575.   selector specified in register BX will be reloaded. DPMI 0.9 may do this,
  576.   but it is not guaranteed.
  577.  
  578. ) We hope you have enough sense not to try to modify your current CS or SS
  579.   descriptor.
  580.  
  581. 2.5 - Function 0008h - Set Segment Limit:
  582. -----------------------------------------
  583.  
  584.   Sets the limit field in the descriptor for the specified segment.
  585.  
  586. In:
  587.   AX     = 0008h
  588.   BX     = selector
  589.   CX:DX  = 32bit segment limit
  590.  
  591. Out:
  592.   if successful:
  593.     carry flag clear
  594.  
  595.   if failed:
  596.     carry flag set
  597.  
  598. Notes:
  599. ) The value supplied to the function in CX:DX is the byte length of the
  600.   segment-1.
  601.  
  602. ) Segment limits greater than or equal to 1M must be page aligned. That is,
  603.   they must have the low 12 bits set.
  604.  
  605. ) This function has an implicit effect on the "G" bit in the segment's
  606.   descriptor.
  607.  
  608. ) Client programs must use the LSL instruction to query the limit for a
  609.   descriptor.
  610.  
  611. ) Under DPMI 1.0/VCPI/XMS/raw, any segment register which contains the
  612.   selector specified in register BX will be reloaded. DPMI 0.9 may do this,
  613.   but it is not guaranteed.
  614.  
  615. ) We hope you have enough sense not to try to modify your current CS or SS
  616.   descriptor.
  617.  
  618. 2.6 - Function 0009h - Set Descriptor Access Rights:
  619. ----------------------------------------------------
  620.  
  621.   Modifies the access rights field in the descriptor for the specified
  622. segment.
  623.  
  624. In:
  625.   AX     = 0009h
  626.   BX     = selector
  627.   CX     = access rights/type word
  628.  
  629. Out:
  630.   if successful:
  631.     carry flag clear
  632.  
  633.   if failed:
  634.     carry flag set
  635.  
  636. Notes:
  637. ) The access rights/type word passed to the function in CX has the following
  638.   format:
  639.  
  640.     Bit: 15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
  641.        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
  642.        | G |B/D| 0 | ? |       ?       | 1 |  DPL  | 1 |C/D|E/C|W/R| A |
  643.        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
  644.  
  645.     G   - 0=byte granular, 1=page granular
  646.     B/D - 0=default 16bit, 1=default 32bit
  647.     DPL - must be equal to caller's CPL
  648.     C/D - 0=data, 1=code
  649.     E/C - data: 0=expand-up, 1=expand-down
  650.           code: must be 0 (non-conforming)
  651.     W/R - data: 0=read, 1=read/write
  652.           code: must be 1 (readable)
  653.     A   - 0=not accessed, 1=accessed
  654.     0   - must be 0
  655.     1   - must be 1
  656.     ?   - ignored
  657.  
  658. ) Client programs should use the LAR instruction to examine the access rights
  659.   of a descriptor.
  660.  
  661. ) Under DPMI 1.0/VCPI/XMS/raw, any segment register which contains the
  662.   selector specified in register BX will be reloaded. DPMI 0.9 may do this,
  663.   but it is not guaranteed.
  664.  
  665. ) We hope you have enough sense not to try to modify your current CS or SS
  666.   descriptor.
  667.  
  668. 2.7 - Function 000Ah - Create Alias Descriptor:
  669. -----------------------------------------------
  670.  
  671.   Creates a new data descriptor that has the same base and limit as the
  672. specified descriptor.
  673.  
  674. In:
  675.   AX     = 000ah
  676.   BX     = selector
  677.  
  678. Out:
  679.   if successful:
  680.     carry flag clear
  681.     AX       = data selector (alias)
  682.  
  683.   if failed:
  684.     carry flag set
  685.  
  686. Notes:
  687. ) The selector supplied to the function may be either a data descriptor or
  688.   a code descriptor. The alias descriptor created is always an expand-up
  689.   writeable data segment.
  690.  
  691. ) The descriptor alias returned by this function will not track changes to the
  692.   original descriptor.
  693.  
  694. 2.8 - Function 000Bh - Get Descriptor:
  695. --------------------------------------
  696.  
  697.   Copies the descriptor table entry for the specified selector into an 8 byte
  698. buffer.
  699.  
  700. In:
  701.   AX     = 000bh
  702.   BX     = selector
  703.   ES:EDI = selector:offset of 8 byte buffer
  704.  
  705. Out:
  706.   if successful:
  707.     carry flag clear
  708.     buffer pointed to by ES:EDI contains descriptor
  709.  
  710.   if failed:
  711.     carry flag set
  712.  
  713. 2.9 - Function 000Ch - Set Descriptor:
  714. --------------------------------------
  715.  
  716.   Copies the contents of an 8 byte buffer into the descriptor for the
  717. specified selector.
  718.  
  719. In:
  720.   AX     = 000ch
  721.   BX     = selector
  722.   ES:EDI = selector:offset of 8 byte buffer containing descriptor
  723.  
  724. Out:
  725.   if successful:
  726.     carry flag clear
  727.  
  728.   if failed:
  729.     carry flag set
  730.  
  731. ) The descriptors access rights/type word at offset 5 within the descriptor
  732.   follows the same format and restrictions as the access rights/type parameter
  733.   CX to the Set Descriptor Access Rights function (0009h).
  734.  
  735. ) Under DPMI 1.0/VCPI/XMS/raw, any segment register which contains the
  736.   selector specified in register BX will be reloaded. DPMI 0.9 may do this,
  737.   but it is not guaranteed.
  738.  
  739. ) We hope you have enough sense not to try to modify your current CS or SS
  740.   descriptor or the descriptor of the buffer.
  741.  
  742. 2.10 - Function 0100h - Allocate DOS Memory Block:
  743. --------------------------------------------------
  744.  
  745.   Allocates low memory through DOS function 48h and allocates it a descriptor.
  746.  
  747. In:
  748.   AX     = 0100h
  749.   BX     = paragraphs to allocate
  750.  
  751. Out:
  752.   if successful:
  753.     carry flag clear
  754.     AX       = real mode segment address
  755.     DX       = protected mode selector for memory block
  756.  
  757.   if failed:
  758.     carry flag set
  759.     AX       = DOS error code
  760.     BX       = size of largest available block
  761.  
  762. 2.11 - Function 0101h - Free DOS Memory Block:
  763. ----------------------------------------------
  764.  
  765.   Frees a low memory block previously allocated by function 0100h.
  766.  
  767. In:
  768.   AX     = 0101h
  769.   DX     = protected mode selector for memory block
  770.  
  771. Out:
  772.   if successful:
  773.     carry flag clear
  774.  
  775.   if failed:
  776.     carry flag set
  777.     AX       = DOS error code
  778.  
  779. 2.12 - Function 0102h - Resize DOS Memory Block:
  780. ------------------------------------------------
  781.  
  782.   Resizes a low memory block previously allocated by function 0100h
  783.  
  784. In:
  785.   AX     = 0102h
  786.   BX     = new block size in paragraphs
  787.   DX     = protected mode selector for memory block
  788.  
  789. Out:
  790.   if successful:
  791.     carry flag clear
  792.  
  793.   if failed:
  794.     carry flag set
  795.     AX       = DOS error code
  796.     BX       = size of largest available block
  797.  
  798. 2.13 - Function 0200h - Get Real Mode Interrupt Vector:
  799. -------------------------------------------------------
  800.  
  801.   Returns the real mode segment:offset for the specified interrupt vector.
  802.  
  803. In:
  804.   AX     = 0200h
  805.   BL     = interrupt number
  806.  
  807. Out:
  808.   always successful:
  809.     carry flag clear
  810.     CX:DX  = segment:offset of real mode interrupt handler
  811.  
  812. Notes:
  813. ) The value returned in CX is a real mode segment address, not a protected
  814.   mode selector.
  815.  
  816. 2.14 - Function 0201h - Set Real Mode Interrupt Vector:
  817. -------------------------------------------------------
  818.  
  819.   Sets the real mode segment:offset for the specified interrupt vector.
  820.  
  821. In:
  822.   AX     = 0201h
  823.   BL     = interrupt number
  824.   CX:DX  = segment:offset of real mode interrupt handler
  825.  
  826. Out:
  827.   always successful:
  828.     carry flag clear
  829.  
  830. Notes:
  831. ) The value passed in CX must be a real mode segment address, not a protected
  832.   mode selector. Consequently, the interrupt handler must either reside in
  833.   DOS memory (below the 1M boundary) or the client must allocate a real mode
  834.   callback address.
  835.  
  836. 2.15 - Function 0204h - Get Protected Mode Interrupt Vector:
  837. ------------------------------------------------------------
  838.  
  839.   Returns the address of the current protected mode interrupt handler for the
  840. specified interrupt.
  841.  
  842. In:
  843.   AX     = 0204h
  844.   BL     = interrupt number
  845.  
  846. Out:
  847.   always successful:
  848.     carry flag clear
  849.     CX:EDX = selector:offset of protected mode interrupt handler
  850.  
  851. Notes:
  852. ) The value returned in CX is a valid protected mode selector, not a real mode
  853.   segment address.
  854.  
  855. 2.16 - Function 0205h - Set Protected Mode Interrupt Vector:
  856. ------------------------------------------------------------
  857.  
  858.   Sets the address of the protected mode interrupt handler for the specified
  859. interrupt.
  860.  
  861. In:
  862.   AX     = 0205h
  863.   BL     = interrupt number
  864.   CX:EDX = selector offset of protected mode interrupt handler
  865.  
  866. Out:
  867.   if successful:
  868.     carry flag clear
  869.  
  870.   if failed:
  871.     carry flag set
  872.  
  873. Notes:
  874. ) The value passed in CX must be a valid protected mode selector, not a real
  875.   mode segment address.
  876.  
  877. 2.17 - Function 0300h - Simulate Real Mode Interrupt:
  878. -----------------------------------------------------
  879.  
  880.   Simulates an interrupt in real mode. The function transfers control to the
  881. address specified by the real mode interrupt vector. The real mode handler
  882. must return by executing an IRET.
  883.  
  884. In:
  885.   AX     = 0300h
  886.   BL     = interrupt number
  887.   BH     = must be 0
  888.   CX     = number of words to copy from the protected mode stack to the real
  889.            mode stack
  890.   ES:EDI = selector:offset of real mode register data structure in the
  891.            following format:
  892.  
  893.            Offset  Length  Contents
  894.            00h     4       EDI
  895.            04h     4       ESI
  896.            08h     4       EBP
  897.            0ch     4       reserved, ignored
  898.            10h     4       EBX
  899.            14h     4       EDX
  900.            18h     4       ECX
  901.            1ch     4       EAX
  902.            20h     2       CPU status flags
  903.            22h     2       ES
  904.            24h     2       DS
  905.            26h     2       FS
  906.            28h     2       GS
  907.            2ah     2       IP (reserved, ignored)
  908.            2ch     2       CS (reserved, ignored)
  909.            2eh     2       SP
  910.            30h     2       SS
  911.  
  912. Out:
  913.   if successful:
  914.     carry flag clear
  915.     ES:EDI = selector offset of modified real mode register data structure
  916.  
  917.   if failed:
  918.     carry flag set
  919.  
  920. Notes:
  921. ) The CS:IP in the real mode register data structure is ignored by this
  922.   function. The appropriate interrupt handler will be called based on the
  923.   value passed in BL.
  924.  
  925. ) If the SS:SP fields in the real mode register data structure are zero, a
  926.   real mode stack will be provided by the host. Otherwise the real mode SS:SP
  927.   will be set to the specified values before the interrupt handler is called.
  928.  
  929. ) The flags specified in the real mode register data structure will be put on
  930.   the real mode interrupt handler's IRET frame. The interrupt handler will be
  931.   called with the interrupt and trace flags clear.
  932.  
  933. ) Values placed in the segment register positions of the data structure must
  934.   be valid for real mode. That is, the values must be paragraph addresses, not
  935.   protected mode selectors.
  936.  
  937. ) The target real mode handler must return with the stack in the same state
  938.   as when it was called. This means that the real mode code may switch stacks
  939.   while it is running, but must return on the same stack that it was called
  940.   on and must return with an IRET.
  941.  
  942. ) When this function returns, the real mode register data structure will
  943.   contain the values that were returned by the real mode interrupt handler.
  944.   The CS:IP and SS:SP values will be unmodified in the data structure.
  945.  
  946. ) It is the caller's responsibility to remove any parameters that were pushed
  947.   on the protected mode stack.
  948.  
  949. 2.18 - Function 0301h - Call Real Mode Procedure With Far Return Frame:
  950. -----------------------------------------------------------------------
  951.  
  952.   Simulates a FAR CALL to a real mode procedure. The called procedure must
  953. return by executing a RETF instruction.
  954.  
  955. In:
  956.   AX     = 0301h
  957.   BH     = must be 0
  958.   CX     = number of words to copy from the protected mode stack to the real
  959.            mode stack
  960.   ES:EDI = selector:offset of real mode register data structure in the
  961.            following format:
  962.  
  963.            Offset  Length  Contents
  964.            00h     4       EDI
  965.            04h     4       ESI
  966.            08h     4       EBP
  967.            0ch     4       reserved, ignored
  968.            10h     4       EBX
  969.            14h     4       EDX
  970.            18h     4       ECX
  971.            1ch     4       EAX
  972.            20h     2       CPU status flags
  973.            22h     2       ES
  974.            24h     2       DS
  975.            26h     2       FS
  976.            28h     2       GS
  977.            2ah     2       IP
  978.            2ch     2       CS
  979.            2eh     2       SP
  980.            30h     2       SS
  981.  
  982. Out:
  983.   if successful:
  984.     carry flag clear
  985.     ES:EDI = selector offset of modified real mode register data structure
  986.  
  987.   if failed:
  988.     carry flag set
  989.  
  990. Notes:
  991. ) The CS:IP in the real mode register data structure specifies the address of
  992.   the real mode procedure to call.
  993.  
  994. ) If the SS:SP fields in the real mode register data structure are zero, a
  995.   real mode stack will be provided by the host. Otherwise the real mode SS:SP
  996.   will be set to the specified values before the procedure is called.
  997.  
  998. ) Values placed in the segment register positions of the data structure must
  999.   be valid for real mode. That is, the values must be paragraph addresses, not
  1000.   protected mode selectors.
  1001.  
  1002. ) The target real mode procedure must return with the stack in the same state
  1003.   as when it was called. This means that the real mode code may switch stacks
  1004.   while it is running, but must return on the same stack that it was called
  1005.   on and must return with a RETF and should not clear the stack of any
  1006.   parameters that were passed to it on the stack.
  1007.  
  1008. ) When this function returns, the real mode register data structure will
  1009.   contain the values that were returned by the real mode procedure. The CS:IP
  1010.   and SS:SP values will be unmodified in the data structure.
  1011.  
  1012. ) It is the caller's responsibility to remove any parameters that were pushed
  1013.   on the protected mode stack.
  1014.  
  1015. 2.19 - Function 0302h - Call Real Mode Procedure With IRET Frame:
  1016. -----------------------------------------------------------------
  1017.  
  1018.   Simulates a FAR CALL with flags pushed on the stack to a real mode routine.
  1019. The real mode procedure must return by executing an IRET instruction or a
  1020. RETF 2.
  1021.  
  1022. In:
  1023.   AX     = 0301h
  1024.   BH     = must be 0
  1025.   CX     = number of words to copy from the protected mode stack to the real
  1026.            mode stack
  1027.   ES:EDI = selector:offset of real mode register data structure in the
  1028.            following format:
  1029.  
  1030.            Offset  Length  Contents
  1031.            00h     4       EDI
  1032.            04h     4       ESI
  1033.            08h     4       EBP
  1034.            0ch     4       reserved, ignored
  1035.            10h     4       EBX
  1036.            14h     4       EDX
  1037.            18h     4       ECX
  1038.            1ch     4       EAX
  1039.            20h     2       CPU status flags
  1040.            22h     2       ES
  1041.            24h     2       DS
  1042.            26h     2       FS
  1043.            28h     2       GS
  1044.            2ah     2       IP
  1045.            2ch     2       CS
  1046.            2eh     2       SP
  1047.            30h     2       SS
  1048.  
  1049. Out:
  1050.   if successful:
  1051.     carry flag clear
  1052.     ES:EDI = selector offset of modified real mode register data structure
  1053.  
  1054.   if failed:
  1055.     carry flag set
  1056.  
  1057. Notes:
  1058. ) The CS:IP in the real mode register data structure specifies the address of
  1059.   the real mode procedure to call.
  1060.  
  1061. ) If the SS:SP fields in the real mode register data structure are zero, a
  1062.   real mode stack will be provided by the host. Otherwise the real mode SS:SP
  1063.   will be set to the specified values before the procedure is called.
  1064.  
  1065. ) The flags specified in the real mode register data structure will be put on
  1066.   the real mode procedure's IRET frame. The procedure will be called with the
  1067.   interrupt and trace flags clear.
  1068.  
  1069. ) Values placed in the segment register positions of the data structure must
  1070.   be valid for real mode. That is, the values must be paragraph addresses, not
  1071.   protected mode selectors.
  1072.  
  1073. ) The target real mode procedure must return with the stack in the same state
  1074.   as when it was called. This means that the real mode code may switch stacks
  1075.   while it is running, but must return on the same stack that it was called
  1076.   on and must return with an IRET or discard the flags from the stack with a
  1077.   RETF 2 and should not clear the stack of any parameters that were passed to
  1078.   it on the stack.
  1079.  
  1080. ) When this function returns, the real mode register data structure will
  1081.   contain the values that were returned by the real mode procedure. The CS:IP
  1082.   and SS:SP values will be unmodified in the data structure.
  1083.  
  1084. ) It is the caller's responsibility to remove any parameters that were pushed
  1085.   on the protected mode stack.
  1086.  
  1087. 2.20 - Function 0303h - Allocate Real Mode Callback Address:
  1088. ------------------------------------------------------------
  1089.  
  1090.   Returns a unique real mode segment:offset, known as a "real mode callback",
  1091. that will transfer control from real mode to a protected mode procedure.
  1092. Callback addresses obtained with this function can be passed by a protected
  1093. mode program to a real mode application, interrupt handler, device driver,
  1094. TSR, etc... so that the real mode program can call procedures within the
  1095. protected mode program.
  1096.  
  1097. In:
  1098.   AX     = 0303h
  1099.   DS:ESI = selector:offset of protected mode procedure to call
  1100.   ES:EDI = selector:offset of 32h byte buffer for real mode register data
  1101.            structure to be used when calling the callback routine.
  1102.  
  1103. Out:
  1104.   if successful:
  1105.     carry flag clear
  1106.     CX:DX  = segment:offset of real mode callback
  1107.  
  1108.   if failed:
  1109.     carry flag set
  1110.  
  1111. Notes:
  1112. ) A descriptor may be allocated for each callback to hold the real mode SS
  1113.   descriptor. Real mode callbacks are a limited system resource. A client
  1114.   should release a callback that it is no longer using.
  1115.  
  1116. 2.21 - Function 0304h - Free Real Mode Callback Address:
  1117. --------------------------------------------------------
  1118.  
  1119.   Releases a real mode callback address that was previously allocated with the
  1120. Allocate Real Mode Callback Address function (0303h).
  1121.  
  1122. In:
  1123.   AX     = 0304h
  1124.   CX:DX  = segment:offset of real mode callback to be freed
  1125.  
  1126. Out:
  1127.   if successful:
  1128.     carry flag clear
  1129.  
  1130.   if failed:
  1131.     carry flag set
  1132.  
  1133. Notes:
  1134. ) Real mode callbacks are a limited system resource. A client should release
  1135.   any callback that it is no longer using.
  1136.  
  1137. 2.22 - Function 0305h - Get State Save/Restore Addresses:
  1138. ---------------------------------------------------------
  1139.  
  1140.   Returns the address of two procedures used to save and restore the state of
  1141. the current task's registers in the mode (protected or real) which is not
  1142. currently executing.
  1143.  
  1144. In:
  1145.   AX     = 0305h
  1146.  
  1147. Out:
  1148.   always successful:
  1149.     carry flag clear
  1150.     AX       = size of buffer in bytes required to save state
  1151.     BX:CX  = segment:offset of real mode routine used to save/restore state
  1152.     SI:EDI = selector:offset of protected mode routine used to save/restore
  1153.          state
  1154.  
  1155. Notes:
  1156. ) The real mode segment:offset returned by this function should be called
  1157.   only in real mode to save/restore the state of the protected mode registers.
  1158.   The protected mode selector:offset returned by this function should be
  1159.   called only in protected mode to save/restore the state of the real mode
  1160.   registers.
  1161.  
  1162. ) Both of the state save/restore procedures are entered by a FAR CALL with the
  1163.   following parameters:
  1164.  
  1165.   AL       = 0 to save state
  1166.            = 1 to restore state
  1167.   ES:(E)DI = (selector or segment):offset of state buffer
  1168.  
  1169.   The state buffer must be at least as large as the value returned in AX by
  1170.   INT 31h function 0305h. The state save/restore procedures do not modify any
  1171.   registers. DI must be used for the buffer offset in real mode, EDI must be
  1172.   used in protected mode.
  1173.  
  1174. ) Some DPMI hosts and VCPI/XMS/raw will not require the state to be saved,
  1175.   indicating this by returning a buffer size of zero in AX. In such cases,
  1176.   that addresses returned by this function can still be called, although they
  1177.   will simply return without performing any useful function.
  1178.  
  1179. ) Clients do not need to call the state save/restore procedures before using
  1180.   INT 31h function 0300h, 0301h, or 0302h. The state save/restore procedures
  1181.   are provided for clients that use the raw mode switch services only.
  1182.  
  1183. 2.23 - Function 0306h - Get Raw Mode Switch Addresses:
  1184. ------------------------------------------------------
  1185.  
  1186.   Returns addresses that can be called for low level mode switching.
  1187.  
  1188. In:
  1189.   AX     = 0306h
  1190.  
  1191. Out:
  1192.   always successful:
  1193.     carry flag clear
  1194.     BX:CX  = segment:offset of real to protected mode switch procedure
  1195.     SI:EDI = selector:offset of protected to real mode switch procedure
  1196.  
  1197. Notes:
  1198. ) The real mode segment:offset returned by this function should be called
  1199.   only in real mode to switch to protected mode. The protected mode
  1200.   selector:offset returned by this function should be called only in protected
  1201.   mode to switch to real mode.
  1202.  
  1203. ) The mode switch procedures are entered by a FAR JMP to the appropriate
  1204.   address with the following parameters:
  1205.  
  1206.   AX    = new DS
  1207.   CX    = new ES
  1208.   DX    = new SS
  1209.   (E)BX = new (E)SP
  1210.   SI    = new CS
  1211.   (E)DI = new (E)IP
  1212.  
  1213.   The processor is placed into the desired mode, and the DS, ES, SS, (E)SP,
  1214.   CS, and (E)IP registers are updated with the specific values. In other
  1215.   words, execution of the client continues in the requested mode at the
  1216.   address provided in registers SI:(E)DI. The values specified to be placed
  1217.   into the segment registers must be appropriate for the destination mode.
  1218.   That is, segment addresses for real mode, and selectors for protected mode.
  1219.  
  1220.   The values in EAX, EBX, ECX, EDX, ESI, and EDI after the mode switch are
  1221.   undefined. EBP will be preserved across the mode switch call so it can be
  1222.   used as a pointer. FS and GS will contain zero after the mode switch.
  1223.  
  1224.   If interrupts are disabled when the mode switch procedure is invoked, they
  1225.   will not be re-enabled by the host (even temporarily).
  1226.  
  1227. ) It is up to the client to save and restore the state of the task when using
  1228.   this function to switch modes. This requires the state save/restore
  1229.   procedures whose addresses can be obtained with INT 31h function 0305h.
  1230.  
  1231. 2.24 - Function 0400h - Get Version:
  1232. ------------------------------------
  1233.  
  1234.   Returns the version of the DPMI Specification implemented by the DPMI host.
  1235. The client can use this information to determine what functions are available.
  1236.  
  1237. In:
  1238.   AX     = 0400h
  1239.  
  1240. Out:
  1241.   always successful:
  1242.     carry flag clear
  1243.     AH       = DPMI major version as a binary number (VCPI/XMS/raw returns 1)
  1244.     AL       = DPMI minor version as a binary number (VCPI/XMS/raw returns 0)
  1245.     BX       = flags:
  1246.          Bits    Significance
  1247.              0       0 = host is 16bit (PMODE/W never runs under one of these)
  1248.              1 = host is 32bit
  1249.          1         0 = CPU returned to V86 mode for reflected interrupts
  1250.              1 = CPU returned to real mode for reflected interrupts
  1251.          2         0 = virtual memory not supported
  1252.              1 = virtual memory supported
  1253.          3-15    reserved
  1254.     CL       = processor type:
  1255.          03h = 80386
  1256.          04h = 80486
  1257.          05h = 80586
  1258.          06h-ffh = reserved
  1259.     DH       = current value of master PIC base interrupt (low 8 IRQs)
  1260.     DL       = current value of slave PIC base interrupt (high 8 IRQs)
  1261.  
  1262. Notes:
  1263. ) The major and minor version numbers are binary, not BCD. So a DPMI 0.9
  1264.   implementation would return AH as 0 and AL as 5ah (90).
  1265.  
  1266. 2.25 - Function 0500h - Get Free Memory Information:
  1267. ----------------------------------------------------
  1268.  
  1269.   Returns information about the amount of available memory. Since DPMI clients
  1270. could be running in a multitasking environment, the information returned by
  1271. this function should be considered advisory.
  1272.  
  1273. In:
  1274.   AX     = 0500h
  1275.   ES:EDI = selector:offset of 48 byte buffer
  1276.  
  1277. Out:
  1278.   if successful:
  1279.     carry flag clear
  1280.     buffer is filled with the following information:
  1281.  
  1282.       Offset  Length  Contents
  1283.       00h     4       Largest available free block in bytes
  1284.       04h     2ch     Other fields only supplied by DPMI
  1285.  
  1286.   if failed:
  1287.     carry flag set
  1288.  
  1289. Notes:
  1290. ) Only the first field of the structure is guaranteed to contain a valid
  1291.   value. Any fields that are not supported by the host will be set to -1
  1292.   (0ffffffffh) to indicate that the information is not available.
  1293.  
  1294. 2.26 - Function 0501h - Allocate Memory Block:
  1295. ----------------------------------------------
  1296.  
  1297.   Allocates a block of extended memory.
  1298.  
  1299. In:
  1300.   AX     = 0501h
  1301.   BX:CX  = size of block in bytes (must be non-zero)
  1302.  
  1303. Out:
  1304.   if successful:
  1305.     carry flag clear
  1306.     BX:CX  = linear address of allocated memory block
  1307.     SI:DI  = memory block handle (used to resize and free block)
  1308.  
  1309.   if failed:
  1310.     carry flag set
  1311.  
  1312. Notes:
  1313. ) The allocated block is guaranteed to have at least dword alignment.
  1314.  
  1315. ) This function does not allocate any descriptors for the memory block. It is
  1316.   the responsibility of the client to allocate and initialize any descriptors
  1317.   needed to access the memory with additional function calls.
  1318.  
  1319. 2.27 - Function 0502h - Free Memory Block:
  1320. ------------------------------------------
  1321.  
  1322.   Frees a memory block previously allocated with the Allocate Memory Block
  1323. function (0501h).
  1324.  
  1325. In:
  1326.   AX     = 0502h
  1327.   SI:DI  = memory block handle
  1328.  
  1329. Out:
  1330.   if successful:
  1331.     carry flag clear
  1332.  
  1333.   if failed:
  1334.     carry flag set
  1335.  
  1336. Notes:
  1337. ) No descriptors are freed by this call. It is the client's responsibility to
  1338.   free any descriptors that it previously allocated to map the memory block.
  1339.   Descriptors should be freed before memory blocks.
  1340.  
  1341. 2.28 - Function 0503h - Resize Memory Block:
  1342. --------------------------------------------
  1343.  
  1344.   Changes the size of a memory block previously allocated with the Allocate
  1345. Memory Block function (0501h).
  1346.  
  1347. In:
  1348.   AX     = 0503h
  1349.   BX:CX  = new size of block in bytes (must be non-zero)
  1350.   SI:DI  = memory block handle
  1351.  
  1352. Out:
  1353.   if successful:
  1354.     carry flag clear
  1355.     BX:CX  = new linear address of memory block
  1356.     SI:DI  = new memory block handle
  1357.  
  1358.   if failed:
  1359.     carry flag set
  1360.  
  1361. Notes:
  1362. ) After this function returns successfully, the previous handle for the memory
  1363.   block is invalid and should not be used anymore.
  1364.  
  1365. ) It is the client's responsibility to update any descriptors that map the
  1366.   memory block with the new linear address after resizing the block.
  1367.  
  1368. 2.29 - Function 0800h - Physical Address Mapping:
  1369. -------------------------------------------------
  1370.  
  1371.   Converts a physical address into a linear address. This functions allows the
  1372. client to access devices mapped at a specific physical memory address.
  1373. Examples of this are the frame buffers of certain video cards in extended
  1374. memory.
  1375.  
  1376. In:
  1377.   AX     = 0800h
  1378.   BX:CX  = physical address of memory
  1379.   SI:DI  = size of region to map in bytes
  1380.  
  1381. Out:
  1382.   if successful:
  1383.     carry flag clear
  1384.     BX:CX  = linear address that can be used to access the physical memory
  1385.  
  1386.   if failed:
  1387.     carry flag set
  1388.  
  1389. Notes:
  1390. ) It is the caller's responsibility to allocate and initialize a descriptor
  1391.   for access to the memory.
  1392.  
  1393. ) Clients should not use this function to access memory below the 1 MB
  1394.   boundary.
  1395.  
  1396. 2.30 - Function 0801h - Free Physical Address Mapping:
  1397. ------------------------------------------------------
  1398.  
  1399.   Releases a mapping of physical to linear addresses that was previously
  1400. obtained with function 0800h.
  1401.  
  1402. In:
  1403.   AX     = 0801h
  1404.   BX:CX  = linear address returned by physical address mapping call
  1405.  
  1406. Out:
  1407.   if successful:
  1408.     carry flag clear
  1409.  
  1410.   if failed:
  1411.     carry flag set
  1412.  
  1413. Notes:
  1414. ) The client should call this function when it is finished using a device
  1415.   previously mapped to linear addresses with function 0801h.
  1416.  
  1417. 2.31 - Function 0900h - Get and Disable Virtual Interrupt State:
  1418. ----------------------------------------------------------------
  1419.  
  1420.   Disables the virtual interrupt flag and returns the previous state of it.
  1421.  
  1422. In:
  1423.   AX     = 0900h
  1424.  
  1425. Out:
  1426.   always successful:
  1427.     carry flag clear
  1428.     AL       = 0 if virtual interrupts were previously disabled
  1429.     AL       = 1 if virtual interrupts were previously enabled
  1430.  
  1431. Notes:
  1432. ) AH is not changed by this function. Therefore the previous state can be
  1433.   restored by simply executing another INT 31h.
  1434.  
  1435. ) A client that does not need to know the prior interrupt state can execute
  1436.   the CLI instruction rather than calling this function. The instruction may
  1437.   be trapped by a DPMI host and should be assumed to be very slow.
  1438.  
  1439. 2.32 - Function 0901h - Get and Enable Virtual Interrupt State:
  1440. ---------------------------------------------------------------
  1441.  
  1442.   Enables the virtual interrupt flag and returns the previous state of it.
  1443.  
  1444. In:
  1445.   AX     = 0901h
  1446.  
  1447. Out:
  1448.   always successful:
  1449.     carry flag clear
  1450.     AL       = 0 if virtual interrupts were previously disabled
  1451.     AL       = 1 if virtual interrupts were previously enabled
  1452.  
  1453. Notes:
  1454. ) AH is not changed by this function. Therefore the previous state can be
  1455.   retstored by simply executing another INT 31h.
  1456.  
  1457. ) A client that does not need to know the prior interrupt state can execute
  1458.   the STI instruction rather than calling this function. The instruction may
  1459.   be trapped by a DPMI host and should be assumed to be very slow.
  1460.  
  1461. 2.33 - Function 0902h - Get Virtual Interrupt State:
  1462. ----------------------------------------------------
  1463.  
  1464.   Returns the current state of the virtual interrupt flag.
  1465.  
  1466. In:
  1467.   AX     = 0902h
  1468.  
  1469. Out:
  1470.   always successful:
  1471.     carry flag clear
  1472.     AL       = 0 if virtual interrupts are disabled
  1473.     AL       = 1 if virtual interrupts are enabled
  1474.  
  1475. Notes:
  1476. ) This function should be used in preference to the PUSHF instruction to
  1477.   examine the interrupt flag, because the PUSHF instruction returns the
  1478.   physical interrupt flag rather than the virtualized interrupt flag. On some
  1479.   DPMI hosts, the physical interrupt flag will always be enabled, even when
  1480.   the hardware interrupts are not being passed through to the client.
  1481.  
  1482. ------------------------------------------------------------------------------
  1483. -------------- 3 - Supported DOS extended INT 21h functions ------------------
  1484. ------------------------------------------------------------------------------
  1485.  
  1486.   For the most part, PMODE/W extends only the most widely used DOS functions.
  1487. The term "extend" means to extend real mode 16:16 pointers which have a limit
  1488. of 1MB into the full protected mode range of 16:32 pointers with a range of
  1489. 4GB. Since DOS can only address memory under 1MB, we must buffer any data that
  1490. is to be passed to or from DOS in low memory. Only DOS functions which use
  1491. 16:16 pointers or segment registers need to be extended. This means that DOS
  1492. functions that are not listed here can still be used provided they don't make
  1493. use of those kinds of parameters. Examples of such functions are INT 21h
  1494. AH=30h or INT 21h AH=2, etc. The following is a detailed list of all functions
  1495. extended by PMODE/W. All segment registers used as parameters must be valid
  1496. protected mode selectors. Any functions that are not listed here will be
  1497. passed on to the real mode INT 21h handler without any buffering or
  1498. modification. This and the other sections on interrupts are provided as
  1499. reference as to how PMODE/W deals with these interrupts. It is assumed the
  1500. reader is familiar with the normal real mode operation of these functions.
  1501.  
  1502. 3.0 - Function 09h - Write String to Standard Output:
  1503. -----------------------------------------------------
  1504.  
  1505. In:
  1506.   AH     = 09h
  1507.   DS:EDX -> '$' terminated string to write
  1508.  
  1509. Out:
  1510.   always successful
  1511.  
  1512. 3.1 - Function 1Ah - Set Disk Transfer Area:
  1513. --------------------------------------------
  1514.  
  1515. In:
  1516.   AH     = 1Ah
  1517.   DS:EDX -> buffer for DTA
  1518.  
  1519. Out:
  1520.   always successful
  1521.  
  1522. Notes:
  1523. ) PMODE/W keeps an internal DTA buffer in low memory that is used to buffer
  1524.   any functions which use the DTA. After calling the real mode DOS function,
  1525.   the data will be transfered into the buffer specified by DS:EDX.
  1526.  
  1527. 3.2 - Function 1Bh - Get Allocation Information for Default Drive:
  1528. ------------------------------------------------------------------
  1529.  
  1530. In:
  1531.   AH     = 1Bh
  1532.  
  1533. Out:
  1534.   always successful:
  1535.     AL     = sectors per cluster
  1536.     ECX    = bytes per sector
  1537.     EDX    = total number of clusters
  1538.     DS:EBX -> media ID byte
  1539.  
  1540. Notes:
  1541. ) This functions simply converts the real mode segment:offset returned by DOS
  1542.   to a protected mode selector:offset.
  1543.  
  1544. 3.3 - Function 1Ch - Get Allocation Information for Specific Drive:
  1545. -------------------------------------------------------------------
  1546.  
  1547. In:
  1548.   AH     = 1Ch
  1549.   DL     = drive number
  1550.  
  1551. Out:
  1552.   if successful:
  1553.     AL     = sectors per cluster
  1554.     ECX    = bytes per sector
  1555.     EDX    = total number of clusters
  1556.     DS:EBX -> media ID byte
  1557.  
  1558.   if failed:
  1559.     AL     = FFh (invalid drive)
  1560.  
  1561. Notes:
  1562. ) This functions simply converts the real mode segment:offset returned by DOS
  1563.   to a protected mode selector:offset.
  1564.  
  1565. 3.4 - Function 1Fh - Get Drive Parameter Block for Default Drive:
  1566. -----------------------------------------------------------------
  1567.  
  1568. In:
  1569.   AH     = 1Fh
  1570.  
  1571. Out:
  1572.   if successful:
  1573.     AL     = 0
  1574.     DS:EBX -> drive parameter block
  1575.  
  1576.   if failed:
  1577.     AL     = FFh (invalid drive)
  1578.  
  1579. Notes:
  1580. ) This functions simply converts the real mode segment:offset returned by DOS
  1581.   to a protected mode selector:offset.
  1582.  
  1583. 3.5 - Function 25h - Set Interrupt Vector:
  1584. ------------------------------------------
  1585.  
  1586. In:
  1587.   AH     = 25h
  1588.   AL     = interrupt number
  1589.   DS:EDX -> interrupt routine
  1590.  
  1591. Out:
  1592.   if successful:
  1593.     carry flag clear
  1594.  
  1595.   if failed:
  1596.     carry flag set
  1597.  
  1598. Notes:
  1599. ) This function is equivalent to INT 31h function 0205h.
  1600.  
  1601. 3.6 - Function 2Fh - Get Disk Transfer Area:
  1602. --------------------------------------------
  1603.  
  1604. In:
  1605.   AH     = 2Fh
  1606.  
  1607. Out:
  1608.   always successful:
  1609.     ES:EBX -> DTA
  1610.  
  1611. Notes:
  1612. ) This function will return the value that was previously set by function 1Ah
  1613.   or the default buffer if function 1Ah was not called.
  1614.  
  1615. 3.7 - Function 32h - Get Drive Parameter Block for Specific Drive:
  1616. ------------------------------------------------------------------
  1617.  
  1618. In:
  1619.   AH     = 32h
  1620.   DL     = drive number
  1621.  
  1622. Out:
  1623.   if successful:
  1624.     AL     = 0
  1625.     DS:EBX -> drive parameter block
  1626.  
  1627.   if failed:
  1628.     AL     = FFh (invalid drive)
  1629.  
  1630. Notes:
  1631. ) This functions simply converts the real mode segment:offset returned by DOS
  1632.   to a protected mode selector:offset.
  1633.  
  1634. 3.8 - Function 34h - Get Address of InDOS Flag:
  1635. -----------------------------------------------
  1636.  
  1637. In:
  1638.   AH = 34h
  1639.  
  1640. Out:
  1641.   always successful:
  1642.     ES:EBX -> InDOS flag
  1643.  
  1644. Notes:
  1645. ) This functions simply converts the real mode segment:offset returned by DOS
  1646.   to a protected mode selector:offset.
  1647.  
  1648. 3.9 - Function 35h - Get Interrupt Vector:
  1649. ------------------------------------------
  1650.  
  1651. In:
  1652.   AH     = 35h
  1653.   AL     = interrupt number
  1654.  
  1655. Out:
  1656.   always successful:
  1657.     ES:EBX -> interrupt routine
  1658.  
  1659. Notes:
  1660. ) This function is equivalent to INT 31h function 0204h.
  1661.  
  1662. 3.10 - Function 39h - Create Subdirectory:
  1663. ------------------------------------------
  1664.  
  1665. In:
  1666.   AH     = 39h
  1667.   DS:EDX -> ASCIIZ path name
  1668.  
  1669. Out:
  1670.   if successful:
  1671.     carry flag clear
  1672.  
  1673.   if failed:
  1674.     carry flag set
  1675.     EAX = error code
  1676.  
  1677. 3.11 - Function 3Ah - Remove Subdirectory:
  1678. ------------------------------------------
  1679.  
  1680. In:
  1681.   AH     = 3Ah
  1682.   DS:EDX -> ASCIIZ path name
  1683.  
  1684. Out:
  1685.   if successful:
  1686.     carry flag clear
  1687.  
  1688.   if failed:
  1689.     carry flag set
  1690.     EAX = error code
  1691.  
  1692. 3.12 - Function 3Bh - Set Directory:
  1693. ------------------------------------
  1694.  
  1695. In:
  1696.   AH     = 3Bh
  1697.   DS:EDX -> ASCIIZ path name
  1698.  
  1699. Out:
  1700.   if successful:
  1701.     carry flag clear
  1702.  
  1703.   if failed:
  1704.     carry flag set
  1705.     EAX = error code
  1706.  
  1707. 3.13 - Function 3Ch - Create File:
  1708. ----------------------------------
  1709.  
  1710. In:
  1711.   AH     = 3Ch
  1712.   CX     = attribute
  1713.   DS:EDX -> ASCIIZ path name
  1714.  
  1715. Out:
  1716.   if successful:
  1717.     carry flag clear
  1718.     EAX = handle
  1719.  
  1720.   if failed:
  1721.     carry flag set
  1722.     EAX = error code
  1723.  
  1724. 3.14 - Function 3Dh - Open File:
  1725. --------------------------------
  1726.  
  1727. In:
  1728.   AH     = 3Dh
  1729.   AL     = open code
  1730.   DS:EDX -> ASCIIZ path name
  1731.  
  1732. Out:
  1733.   if successful:
  1734.     carry flag clear
  1735.     EAX = handle
  1736.  
  1737.   if failed:
  1738.     carry flag set
  1739.     EAX = error code
  1740.  
  1741. 3.15 - Function 3Fh - Read From File:
  1742. -------------------------------------
  1743.  
  1744. In:
  1745.   AH     = 3Fh
  1746.   BX     = file handle
  1747.   ECX     = number of bytes to read
  1748.   DS:EDX -> buffer to read to
  1749.  
  1750. Out:
  1751.   if successful:
  1752.     carry flag clear
  1753.     EAX = number of bytes read
  1754.  
  1755.   if failed:
  1756.     carry flag set
  1757.     EAX = error code
  1758.  
  1759. 3.16 - Function 40h - Write To File:
  1760. ------------------------------------
  1761.  
  1762. In:
  1763.   AH     = 40h
  1764.   BX     = file handle
  1765.   ECX     = number of bytes to write
  1766.   DS:EDX -> buffer to write from
  1767.  
  1768. Out:
  1769.   if successful:
  1770.     carry flag clear
  1771.     EAX = number of bytes written
  1772.  
  1773.   if failed:
  1774.     carry flag set
  1775.     EAX = error code
  1776.  
  1777. 3.17 - Function 41h - Delete File:
  1778. ----------------------------------
  1779.  
  1780. In:
  1781.   AH     = 41h
  1782.   DS:EDX -> ASCIIZ path name
  1783.  
  1784. Out:
  1785.   if successful:
  1786.     carry flag clear
  1787.  
  1788.   if failed:
  1789.     carry flag set
  1790.     EAX = error code
  1791.  
  1792. 3.18 - Function 43h - Get/Set File Attributes:
  1793. ----------------------------------------------
  1794.  
  1795. In:
  1796.   AH     = 43h
  1797.   AL     = function code
  1798.   CX     = desired attributes
  1799.   DS:EDX -> ASCIIZ path name
  1800.  
  1801. Out:
  1802.   if successful:
  1803.     carry flag clear
  1804.     CX = current attributes
  1805.  
  1806.   if failed:
  1807.     carry flag set
  1808.     EAX = error code
  1809.  
  1810. 3.19 - Function 47h - Get Directory Path:
  1811. -----------------------------------------
  1812.  
  1813. In:
  1814.   AH     = 47h
  1815.   DL     = drive number
  1816.   DS:ESI -> buffer for path
  1817.  
  1818. Out:
  1819.   if successful:
  1820.     carry flag clear
  1821.     buffer pointer to by DS:ESI is filled with the path
  1822.  
  1823.   if failed:
  1824.     carry flag set
  1825.     EAX = error code
  1826.  
  1827. 3.20 - Function 48h - Allocate Memory Block:
  1828. --------------------------------------------
  1829.  
  1830. In:
  1831.   AH     = 48h
  1832.   BX     = paragraphs to allocate
  1833.  
  1834. Out:
  1835.   if successful:
  1836.     carry flag clear
  1837.     EAX = selector for memory block
  1838.  
  1839.   if failed:
  1840.     carry flag set
  1841.     EAX = error code
  1842.     EBX = maximum paragraphs available
  1843.  
  1844. Notes:
  1845. ) This function allocates ONLY DOS memory below 1MB.
  1846.  
  1847. ) This function is equivalent to INT 31h function 0100h.
  1848.  
  1849. 3.21 - Function 49h - Free Memory Block:
  1850. ----------------------------------------
  1851.  
  1852. In:
  1853.   AH     = 49h
  1854.   ES     = selector for memory block
  1855.  
  1856. Out:
  1857.   if successful:
  1858.     carry flag clear
  1859.     ES = NULL selector (zeroed to prevent loading an invalid selector)
  1860.  
  1861.   if failed:
  1862.     carry flag set
  1863.     EAX = error code
  1864.  
  1865. Notes:
  1866. ) This function is equivalent to INT 31h function 0101h.
  1867.  
  1868. 3.22 - Function 4Ah - Resize Memory Block:
  1869. ------------------------------------------
  1870.  
  1871. In:
  1872.   AH     = 4Ah
  1873.   BX     = total paragraphs to allocate
  1874.   ES     = selector
  1875.  
  1876. Out:
  1877.   if successful:
  1878.     carry flag clear
  1879.  
  1880.   if failed:
  1881.     carry flag set
  1882.     EAX = error code
  1883.     EBX = maximum paragraphs available for specified memory block
  1884.  
  1885. Notes:
  1886. ) This function is equivalent to INT 31h function 0102h.
  1887.  
  1888. 3.23 - Function 4Bh - Sub-Function 00h - Load and Execute Program:
  1889. ------------------------------------------------------------------
  1890.  
  1891. In:
  1892.   AH     = 4Bh
  1893.   AL     = 00h
  1894.   DS:EDX -> path name
  1895.   ES:EBX -> parameter block
  1896.  
  1897. Out:
  1898.   if successful:
  1899.     carry flag clear
  1900.  
  1901.   if failed:
  1902.     carry flag set
  1903.  
  1904. Notes:
  1905. ) In order to overcome DOS's inability to access data over 1 MB, the
  1906.   environment specified in the parameter block will be copied into an
  1907.   intermediate buffer before being passed on to DOS. The buffer will be
  1908.   allocated through DOS function 48h and freed through 49h when the program
  1909.   is done executing. There must be enough available low memory to hold the
  1910.   environment data or an error will occur. Keep this in mind when passing
  1911.   an environment using spawnle() and related functions.
  1912.  
  1913. 3.24 - Function 4Eh - Search for First Filename Match:
  1914. ------------------------------------------------------
  1915.  
  1916. In:
  1917.   AH     = 4Eh
  1918.   CX     = file attribute
  1919.   DS:EDX -> ASCIIZ path name
  1920.  
  1921. Out:
  1922.   if successful:
  1923.     carry flag clear
  1924.  
  1925.   if failed:
  1926.     carry flag set
  1927.     EAX = error code
  1928.  
  1929. Notes:
  1930. ) PMODE/W keeps an internal DTA buffer in low memory that is used to buffer
  1931.   any functions which use the DTA. After calling the real mode DOS function,
  1932.   the data will be transfered into the buffer specified by function 1Ah or
  1933.   the default buffer if function 1Ah was not called.
  1934.  
  1935. 3.25 - Function 4Fh - Search for Next Filename Match:
  1936. -----------------------------------------------------
  1937.  
  1938. In:
  1939.   AH     = 4Fh
  1940.  
  1941. Out:
  1942.   if successful:
  1943.     carry flag clear
  1944.  
  1945.   if failed:
  1946.     carry flag set
  1947.     EAX = error code
  1948.  
  1949. Notes:
  1950. ) PMODE/W keeps an internal DTA buffer in low memory that is used to buffer
  1951.   any functions which use the DTA. After calling the real mode DOS function,
  1952.   the data will be transfered into the buffer specified by function 1Ah or
  1953.   the default buffer if function 1Ah was not called.
  1954.  
  1955. 3.26 - Function 56h - Rename File:
  1956. ----------------------------------
  1957.  
  1958. In:
  1959.   AH     = 56h
  1960.   DS:EDX -> old filename
  1961.   ES:EDI -> new filename
  1962.  
  1963. Out:
  1964.   if successful:
  1965.     carry flag clear
  1966.  
  1967.   if failed:
  1968.     carry flag set
  1969.     EAX = error code
  1970.  
  1971. ------------------------------------------------------------------------------
  1972. --------------- 4 - Supported mouse extended INT 33h functions ---------------
  1973. ------------------------------------------------------------------------------
  1974.  
  1975.   The mouse functions are technically not part of Watcom C/C++ support because
  1976. they are not used by any of the libraries. But we extend the most popular
  1977. functions because they are so widely used. The functions that need to be
  1978. extended are those that require addresses to be passed in segment registers.
  1979. All other mouse functions not listed here will work if they do not take
  1980. segment registers as parameters. This means that in addition to the functions
  1981. listed here, functions like 0000h, 0001h, 0002h, etc... will work. But
  1982. functions like 0012h and 0018h will not work directly from protected mode
  1983. because they pass or return segment registers as parameters or require low
  1984. memory buffering. You may still use those functions, but you must call them
  1985. through DPMI and make sure that any code or data they use resides in low
  1986. memory and the code is real mode code (like DPMI callback if you wish to pass
  1987. control on to protected mode code from there).
  1988.  
  1989. 4.0 - Function 0009h - Define Graphics Cursor:
  1990. ----------------------------------------------
  1991.  
  1992. In:
  1993.   AX     = 0009h
  1994.   BX     = column of cursor hot spot in bitmap
  1995.   CX     = row of cursor hot spot in bitmap
  1996.   ES:EDX -> mask bitmap
  1997.  
  1998. Out:
  1999.   always successful
  2000.  
  2001. 4.1 - Function 000Ch - Define Interrupt Subroutine Parameters:
  2002. --------------------------------------------------------------
  2003.  
  2004. In:
  2005.   AX     = 000Ch
  2006.   CX     = call mask
  2007.   ES:EDX -> FAR routine
  2008.  
  2009. Out:
  2010.   always successful
  2011.  
  2012. Notes:
  2013. ) This function will use a DPMI real mode callback to pass control from real
  2014.   mode to your protected mode interrupt subroutine.
  2015.  
  2016. ) Calling this function with a FAR routine of 0000:00000000 is analogous to
  2017.   calling the real mode mouse driver with an address of 0000:0000 which will
  2018.   undefine the interrupt subroutine.
  2019.  
  2020. 4.2 - Function 0016h - Save Driver State:
  2021. -----------------------------------------
  2022.  
  2023. In:
  2024.   AX     = 0016h
  2025.   BX     = size of buffer
  2026.   ES:EDX -> buffer for driver state
  2027.  
  2028. Out:
  2029.   always successful
  2030.  
  2031. 4.3 - Function 0017h - Restore Driver State:
  2032. --------------------------------------------
  2033.  
  2034. In:
  2035.   AX     = 0017h
  2036.   BX     = size of buffer
  2037.   ES:EDX -> buffer containing saved state
  2038.  
  2039. Out:
  2040.   always successful
  2041.  
  2042. ------------------------------------------------------------------------------
  2043. ------------------------ End of PMODE/W Documentation ------------------------
  2044. ------------------------------------------------------------------------------
  2045.  
  2046.